package com.yx.changdao.web.aspect;


import com.yx.changdao.common.annotation.AutoLog;
import com.yx.changdao.common.utils.JsonUtils;
import com.yx.changdao.common.utils.SysUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * @Title: AutoLogAspect
 * @Description: 系统日志切面处理类
 * @Auther: Zhangjiashun
 * @Version: 1.0
 * @create 2019/11/5 14:54
 */
@Aspect
@Component
public class AutoLogAspect {
    public static final Logger logger = LoggerFactory.getLogger(AutoLogAspect.class);

    //  对所有带有AutoLog注解的方法记录日志。
    @Pointcut("@annotation(com.yx.changdao.common.annotation.AutoLog)")
    public void logPointCut() {
    }


    /**
     * 方法执行后的返回
     */
    @AfterReturning(returning = "result", pointcut = "logPointCut()")
    public void getReturn(Object result) {
        // 方法执行后的返回值。
        logger.info("return : {}", JsonUtils.serializeNonNull(result));
    }


    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        this.saveSysLog(point, time);

        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        AutoLog syslog = method.getAnnotation(AutoLog.class);
        StringBuilder sb = new StringBuilder();
        if (syslog != null && StringUtils.isNotBlank(syslog.value())) {
            // 获得注解上的描述,操作日志内容
            String annoValue = syslog.value();
            sb.append(annoValue).append("：");
        }


        HttpServletRequest request = SysUtils.getRequest();

        Map<String, String[]> parameterMap = request.getParameterMap();
        StringBuilder parameterString = new StringBuilder();
        if (MapUtils.isNotEmpty(parameterMap)) {
            parameterString.append("?");
            for (String s : parameterMap.keySet()) {
                String parameter = request.getParameter(s);
                parameterString.append(s).append("=").append(parameter).append("&");
            }
            //删除最后多余的 & 符号。
            parameterString.deleteCharAt(parameterString.length() - 1);
        }


        // 请求URL
        String url = request.getRequestURL().toString();
        // 请求方式 get 、 post 等
        String requestMethod = request.getMethod();
        // 请求类名 + 方法名
        String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "()";
        //请求的参数
        Object[] args = joinPoint.getArgs();


        List<Object> objs = new ArrayList<>();
        // 排除空字段和org.apache.catalina.connector.ResponseFacade字段该字段无法序列化
        for (Object arg : args) {
            if (arg != null && !StringUtils.equals("org.apache.catalina.connector.ResponseFacade", arg.getClass().getName())) {
                objs.add(arg);
            }
        }

        logger.info("[" + requestMethod + "]" + sb.toString() + " 请求URL：" + url + parameterString);
        logger.info("请求方法：" + classMethod);

        if (JsonUtils.serializeNonNull(objs) != null) {
            logger.info("参数：" + JsonUtils.serializeNonNull(objs));
        }

        logger.info("执行时间：" + time + "ms");
    }

}